package edu.chalmers.sdx;

import java.io.BufferedReader;
import java.io.IOException;

import android.content.Intent;
import android.nfc.NfcEvent;
import android.util.Log;
import edu.chalmers.targine.ARManager;
import edu.chalmers.targine.Arbject;
import edu.chalmers.targine.GameLayer;
import edu.chalmers.targine.SettingsActivity;
import edu.dhbw.andar.exceptions.AndARException;
import edu.dhbw.andar.util.AssetsFileUtil;
import edu.dhbw.andar.util.BaseFileUtil;
import edu.dhbw.andar.util.ObjParser;
import edu.dhbw.andar.util.ParseException;

public class SkidroidXtreme extends ARManager {
	private OptionInterface optionInterface;
	private NFCFeedback nfcFeedback;
	private Button bSettings;

	private SkidroidArbject currentArbject;
	private SkidroidArbject skierArbject = null;

	public static final String SETTINGS = "settings";
	public static final String SLOPE = "slope";
	public static final String SLOPE1 = "slope_1";
	public static final String SLOPE2 = "slope_2";
	public static final String SLOPE3 = "slope_3";
	public static final String TURN_L = "ski_slope_left_turn";
	public static final String TURN_R = "ski_slope_right_turn";
	public static final String SKIER = "skier_new";
	public static final String NEW_SKIER = "newSkier";
	public static final String CLEAR = "clear";
	public static final String COUNT = "count";
	public static final String NONE = "none";

	@Override
	public void onStart() {
		super.onStart();
		// Selected arbject
		currentArbject = null;
		// Hand interface
		String[] options = { SLOPE1, SLOPE2, SLOPE3, TURN_L, TURN_R, SKIER,
				CLEAR };
		optionInterface = new OptionInterface("activeSlot.png",
				WINDOW_WIDTH / 2, 250);
		optionInterface.loadOptions("action_icons.png", options);
		optionInterface.getNode().setScale(2.0f);
		((GameLayer) (cocosScene.getChildren().get(0)))
				.addComponent(optionInterface);
		bSettings = new Button("d-pad.png", 98, 98, SETTINGS);
		((GameLayer) (cocosScene.getChildren().get(0))).addComponent(bSettings);
		nfcFeedback = new NFCFeedback("pattern_spritesheet.png", 98, 98);
		((GameLayer) (cocosScene.getChildren().get(0)))
				.addComponent(nfcFeedback);
	}

	protected void registerModels() {
		try {
			BaseFileUtil fileUtil = new AssetsFileUtil(getResources()
					.getAssets());
			fileUtil.setBaseFolder("models/");
			ObjParser parser = new ObjParser(fileUtil);
			if (fileUtil != null) {
				BufferedReader fileReader;
				fileReader = fileUtil.getReaderFromName(SLOPE1 + ".obj");
				Log.d("LOAD_MODEL", "Loading " + SLOPE1);
				models.put(SLOPE1, parser.parse(SLOPE1, fileReader));

				fileReader = fileUtil.getReaderFromName(SLOPE2 + ".obj");
				Log.d("LOAD_MODEL", "Loading " + SLOPE2);
				models.put(SLOPE2, parser.parse(SLOPE2, fileReader));

				fileReader = fileUtil.getReaderFromName(SLOPE3 + ".obj");
				Log.d("LOAD_MODEL", "Loading " + SLOPE3);
				models.put(SLOPE3, parser.parse(SLOPE3, fileReader));

				fileReader = fileUtil.getReaderFromName(TURN_R + ".obj");
				Log.d("LOAD_MODEL", "Loading " + TURN_R);
				models.put(TURN_R, parser.parse(TURN_R, fileReader));

				fileReader = fileUtil.getReaderFromName(TURN_L + ".obj");
				Log.d("LOAD_MODEL", "Loading " + TURN_L);
				models.put(TURN_L, parser.parse(TURN_L, fileReader));

				fileReader = fileUtil.getReaderFromName(SKIER + ".obj");
				Log.d("LOAD_MODEL", "Loading " + SKIER);
				models.put(SKIER, parser.parse(SKIER, fileReader));

				registerArbject("0c 10 ef 0f", "linda", "pattern1");
				registerArbject("ae e0 41 d2", "oleander", "pattern3");
				registerArbject("5e 6a 42 d2", "pokeylope", "pattern2");
				registerArbject("9e cc 40 d2", "sasha", "pattern4");
				registerArbject("ee 0a 6d b7", "shield", "pattern_shield");
				registerArbject("de cf 3d d2", "lens", "pattern_lens");
				registerArbject("ee 42 39 d2", "harry", "pattern_harry");
				// registerArbject("6c be 02 06 66 24 16 e0", "harry",
				// "pattern_harry");
				registerArbject("ae 67 3f d2", "tetris", "pattern_tetris");
				registerArbject("ce 37 c6 aa", "axe", "pattern_axe");
				registerArbject("fe c3 c7 aa", "castle", "pattern_castle");
				registerArbject("6e b6 6e b7", "sword", "pattern_sword");
				registerArbject("ee aa 3d d2", "moon", "pattern_moon");
			}
		} catch (AndARException e) {
			// handle the exception, that means: show the user what happened
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	protected void registerArbject(String arbjectID, String patternName,
			String patternFile) throws AndARException {
		arbjects.put(arbjectID, new SkidroidArbject(patternName, patternFile,
				arbjectID, LOCAL_MAC, this));
		serverConnection.sendCommandToServer("currentValue:" + arbjectID + "."
				+ COUNT);
		artoolkit.registerARObject(arbjects.get(arbjectID));
	}

	// Update server with the local skier value
	protected void update() {
		if (skierArbject != null && skierArbject.hasLocalPlayer()) {
			if (skierArbject.isLocalPlayerMarkedForRemoval()) {
				setSharedData(skierArbject.getID(), SKIER,
						skierArbject.getRemovePlayerValue());
				skierArbject.removeLocalPlayer();
				skierArbject = null;
			} else {
				setSharedData(skierArbject.getID(), SKIER,
						skierArbject.getLocalSkierValue());
			}
		}
	}

	protected void onBeamComplete(NfcEvent event) {
	}

	protected void beamReceived(String deviceMac) {
	}

	protected void nfcReceived(Arbject arbject) {
		currentArbject = (SkidroidArbject) arbject;
		nfcFeedback.setImage(currentArbject.getName());
		optionInterface.setVisible(true);
	}

	public void performTapAction(String action, Object object) {
		if (action.equals(SLOPE) && currentArbject != null) {
			String command = (String) object;
			if (command.equals(SLOPE1)) {
				addLevelPart(currentArbject, SLOPE1);
			} else if (command.equals(SLOPE2)) {
				addLevelPart(currentArbject, SLOPE2);
			} else if (command.equals(SLOPE3)) {
				addLevelPart(currentArbject, SLOPE3);
			} else if (command.equals(TURN_L)) {
				addLevelPart(currentArbject, TURN_L);
			} else if (command.equals(TURN_R)) {
				addLevelPart(currentArbject, TURN_R);
			} else if (command.equals(SKIER)) {
				addSkier(currentArbject, LOCAL_MAC);
			} else if (command.equals(CLEAR)) {
				clearArbject(currentArbject);
			}
		} else if (action.equals(SETTINGS)) {
			Intent intent = new Intent(this, SettingsActivity.class);
			startActivity(intent);
		}
	}

	protected void accelerometerChanged(float ax, float ay, float az) {
		if (skierArbject != null) {
			skierArbject.changeSkierAngle(-1f * ay);
		}
	}

	public void serverConnectionEventOccurred(String[] msg) {
		// ((Arbject)arbjects.get(msg[0])).setValue(msg[1], msg[2]);
		if (msg[1].split("_")[0].equals(SLOPE)) {
			SkidroidArbject arbject = (SkidroidArbject) arbjects.get(msg[0]);
			String[] var = msg[2].split(",");
			int partIndex = Integer.parseInt(msg[1].split("_")[1]);
			float posX = Float.parseFloat(var[2]);
			float posY = Float.parseFloat(var[3]);
			if (partIndex < arbject.getLevelSize()) {
				arbject.setLevelPart(partIndex, var[1], posX, posY);
			} else if (partIndex == arbject.levelIndex) {
				arbject.addLevelPart(var[1], posX, posY);
			} else {
				// arbject is missing a level part or something
			}
			// } else if(msg[1].equals(NEW_SKIER)){
			// SkidroidArbject arbject = (SkidroidArbject)arbjects.get(msg[0]);
			// String[] var = msg[2].split(",");
			// String skierID = var[0];
			// float posX = Float.parseFloat(var[1]);
			// float posY = Float.parseFloat(var[2]);
			// float angle = Float.parseFloat(var[3]);
			// arbject.addSkier(models.get(SKIER), SKIER, skierID, posX, posY,
			// angle);
		} else if (msg[1].equals(SKIER)) {
			SkidroidArbject arbject = (SkidroidArbject) arbjects.get(msg[0]);
			String[] var = msg[2].split(",");
			String skierID = var[0];
			float posX = Float.parseFloat(var[1]);
			float posY = Float.parseFloat(var[2]);
			float angle = Float.parseFloat(var[3]);
			if (arbject.hasSkier(skierID) && !skierID.equals(LOCAL_MAC)) {
				arbject.updateSkier(skierID, posX, posY, angle);
			} else if (!arbject.hasSkier(skierID)) {
				arbject.addSkier(models.get(SKIER), SKIER, skierID, posX, posY,
						angle);
			}
		} else if (msg[1].equals(CLEAR)) {
			SkidroidArbject arbject = (SkidroidArbject) arbjects.get(msg[0]);
			arbject.clearLevel();
		} else if (msg[1].equals(COUNT)) {
			int count;
			if (msg[2].equals(NONE)) {
				count = 0;
			} else {
				count = Integer.parseInt(msg[2]);
			}
			for (int i = 0; i < count; i++) {
				serverConnection.sendCommandToServer("currentValue:" + msg[0]
						+ "." + SLOPE + "_" + i);
			}
		}
	}

	public void addSkier(SkidroidArbject arbject, String key) {
		skierArbject = arbject;
		setSharedData(arbject.getID(), SKIER, packSkier(LOCAL_MAC, 0, 0, 0));
		// setSharedData(arbject.getID(), NEW_SKIER, localMAC + "," + 0 + "," +
		// 0 + "," + 0);
	}

	public void clearArbject(SkidroidArbject arbject) {
		setSharedData(arbject.getID(), CLEAR, SLOPE);
	}

	public void addLevelPart(SkidroidArbject arbject, String partType) {
		float xPos = (int) arbject.nextX;
		setSharedData(arbject.getID(), SLOPE + "_" + arbject.levelIndex,
				packPart(arbject.getLevelSize(), partType, xPos, 0));
		// setSharedData(arbject.getID(), SLOPE, arbject.getLevelSize() + "," +
		// partType + "," + xPos + "," + 0);
	}

	private String packSkier(String a, float b, float c, float d) {
		return a + "," + b + "," + c + "," + d;
	}

	private String packPart(int a, String b, float c, float d) {
		return a + "," + b + "," + c + "," + d;
	}
}
